import * as THREE from 'three'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { UnrealBloomPass } from './HuiGuang.js';
import { OutlinePass } from './BianKuang.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js';
import { AfterimagePass } from 'three/examples/jsm/postprocessing/AfterimagePass.js';
import { OutputPass } from 'three/examples/jsm/postprocessing/OutputPass.js';

// 后期处理
export class HouQiChuLi {
	bianKuang = null // 边框
	BLOOM_SCENE = 1 // BLOOM_SCENE发光层
	
	constructor(renderer, scene, camera) {
		let size = renderer.getSize(new THREE.Vector2()) // 渲染器输出canvas的宽度和高度
		renderer.autoClear = false
		
		const ENTIRE_SCENE = 0
		const BLOOM_SCENE = this.BLOOM_SCENE
		
		const bloomLayer = new THREE.Layers();
		bloomLayer.set(BLOOM_SCENE);
		
		const darkMaterial = new THREE.MeshBasicMaterial({ color: 0x000000 });
		const materials = {};
		
		const renderPass = new RenderPass(scene, camera);
		// 辉光，mesh.layers.enable(BLOOM_SCENE)
		const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
		bloomPass.threshold = 0;
		bloomPass.strength = 1.5;
		bloomPass.radius = 0.5;
		const bloomComposer = new EffectComposer(renderer);
		bloomComposer.renderToScreen = false;
		bloomComposer.addPass(renderPass);
		bloomComposer.addPass(bloomPass);
		// 运动幻影
		// let afterimagePass = new AfterimagePass();
		// bloomComposer.addPass(afterimagePass);
		// afterimagePass.uniforms["damp"].value = 0.9;
		
		const finalComposer = new EffectComposer(renderer);
		finalComposer.addPass(renderPass);
		
		let vertexShader = `
			varying vec2 vUv;
			void main() {
				vUv = uv;
				gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
			}
		`
		let fragmentShader = `
			uniform sampler2D baseTexture;
			uniform sampler2D bloomTexture;
			varying vec2 vUv;
			void main() {
				gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );
			}
		`
		const mixPass  = new ShaderPass(
			new THREE.ShaderMaterial({
				uniforms: {
					baseTexture: { value: null },
					bloomTexture: { value: bloomComposer.renderTarget2.texture }
				},
				vertexShader,
				fragmentShader,
				defines: {}
			}), "baseTexture"
		);
		mixPass.needsSwap = true;
		finalComposer.addPass(mixPass);

		// 边框，outlinePass.selectedObjects为边框物体
		let outlinePass = new OutlinePass( size, scene, camera );
		outlinePass.edgeStrength = 10
		outlinePass.edgeGlow = 1
		outlinePass.edgeThickness = 4
		outlinePass.pulsePeriod  = 0
		outlinePass.visibleEdgeColor.set( '#0af' )
		outlinePass.hiddenEdgeColor.set( '#0af' )
		this.bianKuang = outlinePass
		finalComposer.addPass( outlinePass );
		
		const outputPass = new OutputPass();
		finalComposer.addPass( outputPass );
		// 抗锯齿放最后
		let effectFXAA = new ShaderPass( FXAAShader );
		renderer.getSize(new THREE.Vector2())
		effectFXAA.uniforms[ 'resolution' ].value.set( 1 / size.x, 1 / size.y );
		finalComposer.addPass( effectFXAA );
		
		function renderBloom() {
			scene.traverse(darkenNonBloomed);
			bloomComposer.render();
			scene.traverse(restoreMaterial);
		}
		
		function darkenNonBloomed(obj) {
			if (obj.isMesh && bloomLayer.test(obj.layers) === false) {
				materials[obj.uuid] = obj.material;
				obj.material = darkMaterial;
			}
			if (obj.isSprite) {
				obj.userData.xianShi = obj.visible
				obj.visible = false
			}
		}
		
		function restoreMaterial(obj) {
			if (materials[obj.uuid]) {
				obj.material = materials[obj.uuid];
				delete materials[obj.uuid];
			}
			if (obj.isSprite) obj.visible = obj.userData.xianShi
		}
		
		this.xuanRan = function () {
			// render scene with bloom
			renderBloom();
			// render the entire scene, then render bloom scene on top
			finalComposer.render();
		}
	}
}
